package com.sunny.excel.excel.factory;



import com.sunny.excel.annotation.Excel;
import com.sunny.excel.excel.build.ExcelBuilder;


import com.sunny.excel.excel.build.impl.HasExcelColExcelBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * 开启excel扫描才 加入容器
 */

@Component
public class ExcelBuilderFactory {
    @Value("${excel.root.package:com}") private String rootPackage;

    private Map<Class<?>, ExcelBuilder<?>> excelBuilderMap = new HashMap<>();

    @PostConstruct
    public void init() {
        processExcelMarkedDataClass();
    }

    @Autowired
    public void setExcelBuilders(List<ExcelBuilder<?>> excelBuilders) {
        for (ExcelBuilder<?> excelBuilder : excelBuilders) {
            this.excelBuilderMap.put(excelBuilder.getSerializationClass(), excelBuilder);
        }
    }

    private void processExcelMarkedDataClass() {
        try {
            Set<Class<?>> classes = findExcelMarkedClasses();
            for (Class<?> clazz : classes) {
                excelBuilderMap.put(clazz, new HasExcelColExcelBuilder<>(clazz));
            }
        } catch (ClassNotFoundException e) {
            //logger.error("failed to read Excel class", e);
        }
    }

    private Set<Class<?>> findExcelMarkedClasses() throws ClassNotFoundException {
        final ClassPathScanningCandidateComponentProvider provider =
            new ClassPathScanningCandidateComponentProvider(false);
        provider.addIncludeFilter(new AnnotationTypeFilter(Excel.class));
        final Set<BeanDefinition> classes = provider.findCandidateComponents(rootPackage);
        Set<Class<?>> classSet = new HashSet<>();
        for (BeanDefinition beanDefinition : classes) {
            classSet.add(Class.forName(beanDefinition.getBeanClassName()));
        }
        return classSet;
    }

    public <T> ExcelBuilder<T> findExcelBuilder(Class<T> dataClass) {
        ExcelBuilder<T> excelBuilder = (ExcelBuilder<T>) excelBuilderMap.get(dataClass);

        if (excelBuilder == null) {
            throw new RuntimeException("excelBuilder not find error");
        }

        return excelBuilder;
    }

}
